package org.teamswift.crow.rbac.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.shiro.authz.Permission;
import org.hibernate.annotations.*;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.teamswift.crow.rbac.annotation.OrganizationLimited;
import org.teamswift.crow.rbac.common.ICrowUser;
import org.teamswift.crow.rbac.vo.CrowUserVo;
import org.teamswift.crow.rest.annotation.I18N;
import org.teamswift.crow.rest.annotation.SystemGeneratedValue;
import org.teamswift.crow.rest.common.BaseCrowEntity;

import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

@EqualsAndHashCode(callSuper = true)
@Entity
@Data
@Table(
        uniqueConstraints = {
                @UniqueConstraint(columnNames = {
                        "organizationId", "username",
                })
        }
)
@FilterDefs({
        @FilterDef(
                name = "orgFilter",
                parameters = @ParamDef(name = "organization_id", type = "integer")
        )
})
@Filters({
        @Filter(name = "orgFilter", condition = "organization_id = :organization_id"),
})
@OrganizationLimited
@EntityListeners(AuditingEntityListener.class)
public class CrowUser extends BaseCrowEntity<Integer, CrowUserVo> implements ICrowUser<CrowUserVo> {

    @Id
    @I18N("crow.id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Override
    public Integer gtId() {
        return id;
    }

    @Column(nullable = false, length = 50)
    private String username;

    @Column(nullable = false, length = 50)
    private String name;

    @Column(nullable = false, length = 50, unique = true)
    private String mobile;

    @Column(length = 100)
    private String email;

    @Column(length = 150)
    @JsonIgnore
    @SystemGeneratedValue
    private String password;

    @Column(nullable = false, length = 50)
    @SystemGeneratedValue
    @JsonIgnore
    private String salt;

    @Transient
    @SystemGeneratedValue
    private Set<CrowRole> roles;

    @Transient
    @SystemGeneratedValue
    private Set<String> rolesName;

    @Transient
    @SystemGeneratedValue
    private Set<CrowAuthority> authorities;

    @Transient
    @SystemGeneratedValue
    private Set<Permission> permissions;

    private Integer organizationId;

    @SystemGeneratedValue
    @Column(updatable = false)
    private boolean su = false;

    public Set<String> getRolesName() {
        if(roles == null) {
            return new HashSet<>();
        }
        return roles.stream().map(CrowRole::getName).collect(Collectors.toSet());
    }

    @Override
    public void setId(Integer id) {
        this.id = id;
    }
}
